package com.xy.service.calculate.lirun.temu;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xy.api.constant.LadderCostAttributeConstant;
import com.xy.api.constant.UnitConstant;
import com.xy.api.constant.enums.LadderCostBizCodeEnum;
import com.xy.api.constant.enums.UnitTypeEnum;
import com.xy.api.model.dto.calculate.lirun.temu.TemuLirunProductFormDTO;
import com.xy.api.model.dto.calculate.lirun.temu.TemuLirunProductInstanceDTO;
import com.xy.api.model.request.calculate.lirun.temu.SaveTemuLirunProductFormRequest;
import com.xy.api.service.calculate.ILadderCostService;
import com.xy.api.service.calculate.lirun.temu.ITemuLirunProductInstanceService;
import com.xy.api.service.calculate.lirun.temu.ITemuLirunProductService;
import com.xy.api.service.common.IUnitService;
import com.xy.auth.UserContext;
import com.xy.mapper.calculate.lirun.temu.TemuLirunProductFormMapper;
import com.xy.mapper.calculate.lirun.temu.TemuLirunProductInstanceMapper;
import com.xy.mapper.calculate.lirun.temu.TemuLirunProductMapper;
import com.xy.model.po.calculate.lirun.temu.TemuLirunProductFormPO;
import com.xy.model.po.calculate.lirun.temu.TemuLirunProductInstancePO;
import com.xy.model.po.calculate.lirun.temu.TemuLirunProductPO;
import com.xy.utils.CustomBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TemuLirunProductInstanceServiceImpl implements ITemuLirunProductInstanceService {

    @Autowired
    private ITemuLirunProductService temuLirunProductService;

    @Autowired
    private TemuLirunProductMapper temuLirunProductMapper;

    @Autowired
    private TemuLirunProductFormMapper temuLirunProductFormMapper;

    @Autowired
    private TemuLirunProductInstanceMapper temuLirunProductInstanceMapper;

    @Autowired
    private ILadderCostService ladderCostService;

    @Autowired
    private IUnitService unitService;

    @Override
    public List<TemuLirunProductFormDTO> queryTemuLirunInstanceList(Long id) {
        Assert.notNull(id, "temu利润核算项目ID必填");
        LambdaQueryWrapper<TemuLirunProductFormPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(TemuLirunProductFormPO::getIsDeleted, 0)
                .eq(TemuLirunProductFormPO::getTemuLirunProductId, id);
        List<TemuLirunProductFormPO> temuLirunProductFormPOS = temuLirunProductFormMapper.selectList(queryWrapper);
        List<TemuLirunProductFormDTO> list = CustomBeanUtil.copyListProperties(temuLirunProductFormPOS, TemuLirunProductFormDTO::new);
        fillTemuLirunProductInstance(list, id);
        return list;
    }

    /**
     * 填充计算出来的信息
     *
     * @param list
     * @param temuLirunProductId temu利润核算项目ID
     */
    private void fillTemuLirunProductInstance(List<TemuLirunProductFormDTO> list, Long temuLirunProductId) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        LambdaQueryWrapper<TemuLirunProductInstancePO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(TemuLirunProductInstancePO::getIsDeleted, 0)
                .eq(TemuLirunProductInstancePO::getTemuLirunProductId, temuLirunProductId);
        List<TemuLirunProductInstancePO> temuLirunProductInstancePOS = temuLirunProductInstanceMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(temuLirunProductInstancePOS)) {
            return;
        }
        List<TemuLirunProductInstanceDTO> instanceList = CustomBeanUtil.copyListProperties(temuLirunProductInstancePOS, TemuLirunProductInstanceDTO::new);
        Map<Long, List<TemuLirunProductInstanceDTO>> instanceMap = instanceList.stream().collect(Collectors.groupingBy(e -> e.getTemuLirunProductFormId()));

        for (TemuLirunProductFormDTO form : list) {
            Long formId = form.getId();
            if (instanceMap.containsKey(formId)) {
                List<TemuLirunProductInstanceDTO> formInstanceList = instanceMap.get(formId);
                for (TemuLirunProductInstanceDTO instance : formInstanceList) {
                    if (Objects.equals(instance.getType(), 0)) {
                        //佐川
                        form.setZuochuanInstance(instance);
                    } else if (Objects.equals(instance.getType(), 1)) {
                        //across
                        form.setAcrossInstance(instance);
                    }
                }
            }
        }
    }

    @Override
    public void saveTemuLirunForm(SaveTemuLirunProductFormRequest request) {
        Long temuLirunProductId = request.getTemuLirunProductId();
        Assert.notEmpty(request.getFormList(), "提交数据不能为空");

        List<TemuLirunProductFormDTO> formList = request.getFormList();
        for (TemuLirunProductFormDTO form : formList) {
            TemuLirunProductFormPO record = new TemuLirunProductFormPO();
            BeanUtils.copyProperties(form, record);
            record.setTemuLirunProductId(temuLirunProductId);
            if (null != form.getId()) {
                record.setUpdateBy(UserContext.get().getId());
                temuLirunProductFormMapper.updateById(record);
            } else {
                record.setCreateBy(UserContext.get().getId());
                temuLirunProductFormMapper.insert(record);
            }
        }
        temuLirunProductService.updateTemuLirunProductStatus(temuLirunProductId, 0);
    }

    @Override
    public void deleteTemuLirunForm(Long temuLirunProductFormId) {
        TemuLirunProductFormPO deleteRecord = new TemuLirunProductFormPO();
        deleteRecord.setId(temuLirunProductFormId);
        deleteRecord.setIsDeleted(1);
        deleteRecord.setUpdateBy(UserContext.get().getId());
        temuLirunProductFormMapper.updateById(deleteRecord);
    }

    @Override
    public TemuLirunProductFormDTO addForm(TemuLirunProductFormDTO request) {
        TemuLirunProductFormPO record = new TemuLirunProductFormPO();
        CustomBeanUtil.copyProperties(request, record);
        temuLirunProductFormMapper.insert(record);
        request.setId(record.getId());
        return request;
    }

    @Override
    public void calculateTemuLirunForm(Long temuLirunProductId) {
        Assert.notNull(temuLirunProductId, "TEMU利润核算项目ID必填");
        LambdaQueryWrapper<TemuLirunProductFormPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(TemuLirunProductFormPO::getIsDeleted, 0)
                .eq(TemuLirunProductFormPO::getTemuLirunProductId, temuLirunProductId);
        List<TemuLirunProductFormPO> temuLirunProductFormPOS = temuLirunProductFormMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(temuLirunProductFormPOS)) {
            return;
        }
        TemuLirunProductPO temuLirunProductPO = temuLirunProductMapper.selectById(temuLirunProductId);
        List<TemuLirunProductFormDTO> list = CustomBeanUtil.copyListProperties(temuLirunProductFormPOS, TemuLirunProductFormDTO::new);
        for (TemuLirunProductFormDTO temuLirunProductForm : list) {
            temuLirunProductForm.validateBeforeCalculate();

            calculateTemuLirun(temuLirunProductForm, temuLirunProductPO);
        }
    }

    private void calculateTemuLirun(TemuLirunProductFormDTO form, TemuLirunProductPO temuLirunProduct) {
        BigDecimal temuQuotePrice = form.getTemuQuotePrice();
        BigDecimal hundred = BigDecimal.valueOf(100);

        //周长（单位为t_maori_product#product_unit）
        BigDecimal productPerimeter = form.getProductLength().add(form.getProductWidth()).add(form.getProductHeight()).setScale(2, RoundingMode.HALF_UP);

        //产品体积（单位为立方米）
        String productUnit = temuLirunProduct.getProductUnit();


        BigDecimal productLength = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getProductLength());
        BigDecimal productWidth = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getProductWidth());
        BigDecimal productHeight = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getProductHeight());
        BigDecimal productVolume = productLength.multiply(productWidth).multiply(productHeight).setScale(4, RoundingMode.HALF_UP);

        //装箱体积（单位为立方米）
        BigDecimal packetLength = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getPacketLength());
        BigDecimal packetWidth = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getPacketWidth());
        BigDecimal packetHeight = unitService.convertUnit(UnitTypeEnum.LENGTH.getCode(), productUnit, UnitConstant.LengthUnitEnum.M.getCode(), form.getPacketHeight());
        BigDecimal packetVolume = packetLength.multiply(packetWidth).multiply(packetHeight).setScale(4, RoundingMode.HALF_UP);

        //单件总重
        BigDecimal productPackageWeight = form.getPackageWeight().add(form.getProductWeight());

        //退款
        BigDecimal refund = form.getRefundPer().divide(hundred).multiply(temuQuotePrice).setScale(2, RoundingMode.HALF_UP);

        //折扣
        BigDecimal discount = form.getDiscountPer().divide(hundred).multiply(temuQuotePrice).setScale(2, RoundingMode.HALF_UP);

        //头程运费
        BigDecimal headFreightPrice = temuLirunProduct.getHeadFreightPrice();
        BigDecimal internationalShippingCost = packetVolume.divide(BigDecimal.valueOf(form.getOuterCartonPackCount()), 6, RoundingMode.HALF_UP).multiply(headFreightPrice).setScale(2, RoundingMode.HALF_UP);
        form.setInternationalShippingCost(internationalShippingCost);

        //税金
        BigDecimal taxPer = temuLirunProduct.getTaxPer().divide(BigDecimal.valueOf(100), 6, RoundingMode.HALF_UP);
        BigDecimal tax = form.getAmPrice().multiply(taxPer).setScale(2, RoundingMode.HALF_UP);

        //仓储-海外仓
        BigDecimal foreignWarehousePrice = temuLirunProduct.getForeignWarehousePrice();
        BigDecimal foreignWarehouseStorage = foreignWarehousePrice.multiply(productVolume).setScale(2, RoundingMode.HALF_UP);
        form.setForeignWarehouseStorage(foreignWarehouseStorage);


        //佐川配送费-总
        Map<String, BigDecimal> zuochuanValueMap = new HashMap<>();
        zuochuanValueMap.put(LadderCostAttributeConstant.ZuochuanDistribution.PERIMETER, productPerimeter);
        zuochuanValueMap.put(LadderCostAttributeConstant.ZuochuanDistribution.WEIGHT, productPackageWeight);
        BigDecimal zuochuanDistributionCost = ladderCostService.getLadderCost(LadderCostBizCodeEnum.ZUOCHUAN_DISTRIBUTION_PRICE.getCode(), zuochuanValueMap);
        BigDecimal zuochuanDistributionCostTotal = zuochuanDistributionCost.add(form.getSetupCost()).setScale(2, RoundingMode.HALF_UP);

        //总成本-海外仓-佐川
        BigDecimal zuochaunTotalOverseasWarehouseCost = (internationalShippingCost.add(form.getPurchaseCost()))
                .divide(BigDecimal.valueOf(0.047), 6, RoundingMode.HALF_UP)
                .add(tax)
                .add(zuochuanDistributionCostTotal)
                .add(foreignWarehouseStorage)
                .setScale(2, RoundingMode.HALF_UP);

        //佐川-补贴金额
        Map<String, BigDecimal> zuochuanSubsidyMap = new HashMap<>();
        zuochuanSubsidyMap.put(LadderCostAttributeConstant.ZuochuanDistribution.SUBSIDY, temuQuotePrice);
        BigDecimal zuochuanSubsidy = ladderCostService.getLadderCost(LadderCostBizCodeEnum.ZUOCHUAN_TEMU_LIRUN_SUBSIDY.getCode(), zuochuanSubsidyMap);

        //佐川-利润额
        BigDecimal zuochuanProfit = temuQuotePrice
                .subtract(zuochaunTotalOverseasWarehouseCost)
                .subtract(refund)
                .subtract(discount)
                .add(zuochuanSubsidy)
                .setScale(2, RoundingMode.HALF_UP);

        //佐川-利润率
        BigDecimal zuochuanProfitMargin = zuochuanProfit.divide(temuQuotePrice, 4, RoundingMode.HALF_UP).multiply(hundred);

        //Across保管费
        BigDecimal acrossStoragePrice = temuLirunProduct.getAcrossStoragePrice();
        BigDecimal acrossStorageCost = acrossStoragePrice.multiply(productVolume).setScale(2, RoundingMode.HALF_UP);

        //Across配送费-总
        Map<String, BigDecimal> acrossValueMap = new HashMap<>();
        acrossValueMap.put(LadderCostAttributeConstant.AcrossDistribution.PERIMETER, productPerimeter);
        acrossValueMap.put(LadderCostAttributeConstant.AcrossDistribution.WEIGHT, productPackageWeight);
        BigDecimal acrossDistributionCost = ladderCostService.getLadderCost(LadderCostBizCodeEnum.ACROSS_DISTRIBUTION_PRICE.getCode(), acrossValueMap);
        BigDecimal acrossDistributionCostTotal = acrossDistributionCost
                .add(form.getPerItemMiscellaneousCost())
                .add(acrossStorageCost)
                .setScale(2, RoundingMode.HALF_UP);

        //总成本-海外仓-across
        BigDecimal acrossTotalOverseasWarehouseCost = (internationalShippingCost.add(form.getPurchaseCost()))
                .divide(BigDecimal.valueOf(0.047), 6, RoundingMode.HALF_UP)
                .add(tax)
                .add(acrossDistributionCostTotal)
                .add(foreignWarehouseStorage)
                .setScale(2, RoundingMode.HALF_UP);

        //across-补贴金额
        Map<String, BigDecimal> acrossSubsidyMap = new HashMap<>();
        acrossSubsidyMap.put(LadderCostAttributeConstant.AcrossDistribution.SUBSIDY, temuQuotePrice);
        BigDecimal acrossSubsidy = ladderCostService.getLadderCost(LadderCostBizCodeEnum.ACROSS_TEMU_LIRUN_SUBSIDY.getCode(), acrossSubsidyMap);

        //across-利润额
        BigDecimal acrossProfit = temuQuotePrice
                .subtract(acrossTotalOverseasWarehouseCost)
                .subtract(refund)
                .subtract(discount)
                .add(acrossSubsidy)
                .setScale(2, RoundingMode.HALF_UP);

        //across-利润率
        BigDecimal acrossProfitMargin = acrossProfit.divide(temuQuotePrice, 4, RoundingMode.HALF_UP).multiply(hundred);

        updateTemuLirunProductFormCalculate(form);

        clearTemuLirunProductInstance(form.getId());

        TemuLirunProductInstancePO zuochuanInstance = new TemuLirunProductInstancePO();
        zuochuanInstance.setTemuLirunProductId(temuLirunProduct.getId());
        zuochuanInstance.setTemuLirunProductFormId(form.getId());
        zuochuanInstance.setType(0);
        zuochuanInstance.setProfit(zuochuanProfit);
        zuochuanInstance.setProfitMargin(zuochuanProfitMargin);
        zuochuanInstance.setTotalOverseasWarehouseCost(zuochaunTotalOverseasWarehouseCost);
        zuochuanInstance.setDistributionTotalCost(zuochuanDistributionCostTotal);
        zuochuanInstance.setDistributionCost(zuochuanDistributionCost);
        temuLirunProductInstanceMapper.insert(zuochuanInstance);

        TemuLirunProductInstancePO acrossInstance = new TemuLirunProductInstancePO();
        acrossInstance.setTemuLirunProductId(temuLirunProduct.getId());
        acrossInstance.setTemuLirunProductFormId(form.getId());
        acrossInstance.setType(1);
        acrossInstance.setProfit(acrossProfit);
        acrossInstance.setProfitMargin(acrossProfitMargin);
        acrossInstance.setTotalOverseasWarehouseCost(acrossTotalOverseasWarehouseCost);
        acrossInstance.setDistributionTotalCost(acrossDistributionCostTotal);
        acrossInstance.setDistributionCost(acrossDistributionCost);
        acrossInstance.setStorageCost(acrossStorageCost);
        temuLirunProductInstanceMapper.insert(acrossInstance);

        temuLirunProductService.updateTemuLirunProductStatus(temuLirunProduct.getId(), 1);
    }

    private void updateTemuLirunProductFormCalculate(TemuLirunProductFormDTO form) {
        TemuLirunProductFormPO record = new TemuLirunProductFormPO();
        record.setId(form.getId());
        record.setInternationalShippingCost(form.getInternationalShippingCost());
        record.setForeignWarehouseStorage(form.getForeignWarehouseStorage());

        temuLirunProductFormMapper.updateById(record);
    }


    private void clearTemuLirunProductInstance(Long temuLirunProductFormId) {
        LambdaQueryWrapper<TemuLirunProductInstancePO> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(TemuLirunProductInstancePO::getTemuLirunProductFormId, temuLirunProductFormId);

        TemuLirunProductInstancePO deleteRecord = new TemuLirunProductInstancePO();
        deleteRecord.setIsDeleted(1);
        deleteRecord.setUpdateBy(UserContext.get().getId());
        deleteRecord.setUpdateTime(new Date());
        temuLirunProductInstanceMapper.update(deleteRecord, deleteWrapper);
    }


}
